package carmesi.webprovider;

import java.io.IOException;
import java.net.URL;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import javax.swing.JComponent;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import org.netbeans.api.java.project.classpath.ProjectClassPathModifier;
import org.netbeans.api.project.libraries.Library;
import org.netbeans.api.project.libraries.LibraryManager;
import org.netbeans.modules.j2ee.dd.api.common.InitParam;
import org.netbeans.modules.j2ee.dd.api.web.DDProvider;
import org.netbeans.modules.j2ee.dd.api.web.WebApp;
import org.netbeans.modules.web.api.webmodule.WebModule;
import org.netbeans.modules.web.spi.webmodule.WebModuleExtender;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.filesystems.JarFileSystem;
import org.openide.filesystems.URLMapper;
import org.openide.util.Exceptions;
import org.openide.util.HelpCtx;

/**
 *
 * @author Victor
 */
public class CarmesiWebModuleExtender extends WebModuleExtender {
    private WebModule webModule;
    private Set<ChangeListener> listeners=new CopyOnWriteArraySet<ChangeListener>();

    private CarmesiConfigurationPanel panel;

    public CarmesiWebModuleExtender(WebModule webModule) {
        this.webModule = webModule;
    }
    
    @Override
    public void addChangeListener(ChangeListener cl) {
        listeners.add(cl);
    }

    @Override
    public void removeChangeListener(ChangeListener cl) {
        listeners.remove(cl);
    }
    
    void fireChangeEvent(){
        ChangeEvent event=new ChangeEvent(this);
        for(ChangeListener listener:listeners){
            listener.stateChanged(event);
        }
    }

    @Override
    public JComponent getComponent() {
        int maxAgeParam=CarmesiFramework.getInstance().getDefaultCookieMaxAge();
        String classnameParam=CarmesiFramework.getInstance().getDefaultJsonSerializerClassname();
        boolean automaticGenerationParam=CarmesiFramework.getInstance().getDefaultRequestAttributeAutomaticGeneration();
        try {
            DDProvider ddProvider = DDProvider.getDefault();
            if(webModule != null && webModule.getDeploymentDescriptor() != null){
                WebApp webApp = ddProvider.getDDRoot(webModule.getDeploymentDescriptor());
                for(InitParam param:webApp.getContextParam()){
                    if(param.getParamName().equals(CarmesiFramework.getInstance().getCookieMaxAgeParamName())){
                        try{
                            maxAgeParam=Integer.parseInt(param.getParamValue());
                        }catch(NumberFormatException ex){

                        }
                    }else if(param.getParamName().equals(CarmesiFramework.getInstance().getJsonSerializerClassnameParamName())){
                        classnameParam=param.getParamValue();
                    }else if(param.getParamName().equals(CarmesiFramework.getInstance().getRequestAttributeAutomaticGenerationParamName())){
                        automaticGenerationParam=Boolean.parseBoolean(param.getParamValue());
                    }
                }
            }
        } catch (IOException ex) {
            Exceptions.printStackTrace(ex);
        }
        if (panel == null) {
            panel = new CarmesiConfigurationPanel();
            panel.setCarmesiLibrariesOptions(getCarmesiLibraries());
            panel.setJsonSerializerClassnameOptions(CarmesiFramework.getInstance().getIncludedJsonSerializers());
        }
        
        //configuration values
        panel.setCookieMaxAge(maxAgeParam);
        panel.setAutomaticGeneration(automaticGenerationParam);
        panel.setJsonSerializerClassname(classnameParam);
        
        
        panel.setEnabled(webModule != null? !CarmesiWebFrameworkProvider.isCarmesiInWebModule(webModule): true);
        return panel;
    }

    @Override
    public HelpCtx getHelp() {
        return new HelpCtx("carmesi.configuration");
    }

    @Override
    public void update() {
        
    }

    @Override
    public boolean isValid() {
        return true;
    }

    public List<Library> getCarmesiLibraries() {
        List<Library> carmesiLibraries = new LinkedList<Library>();
        for (Library lib : LibraryManager.getDefault().getLibraries()) {
            if (lib.getDisplayName().startsWith("Carmesi") && lib.getType().equals("j2se")) {
                List<URL> content = lib.getContent("classpath");
                for (URL url : content) {
                    url = FileUtil.getArchiveFile(url);
                    if (url == null) {
                        continue;
                    }
                    FileObject fileObject = URLMapper.findFileObject(url);
                    try {
                        JarFileSystem system = new JarFileSystem(FileUtil.toFile(fileObject));
                        FileObject resource = system.findResource(CarmesiWebFrameworkProvider.carmesiResource);
                        if (resource != null) {
                            carmesiLibraries.add(lib);
                        }
                    } catch (IOException ex) {
                    }
                }
            }
        }
        return carmesiLibraries;
    }

    @Override
    public Set<org.openide.filesystems.FileObject> extend(WebModule wm) {
        Library carmesiLibrary = panel.getCarmesiLibrary();
        if (carmesiLibrary != null && wm.getJavaSources().length > 0) {
            try {
                ProjectClassPathModifier.addLibraries(new Library[]{carmesiLibrary}, wm.getJavaSources()[0], "classpath/compile");
                Map<String, String> parameters = new HashMap<String, String>();
                if (panel.getCookieMaxAge() != CarmesiFramework.getInstance().getDefaultCookieMaxAge()) {
                    parameters.put(CarmesiFramework.getInstance().getCookieMaxAgeParamName(), String.valueOf(panel.getCookieMaxAge()));
                }
                if (panel.getAutomaticGeneration() != CarmesiFramework.getInstance().getDefaultRequestAttributeAutomaticGeneration()) {
                    parameters.put(CarmesiFramework.getInstance().getRequestAttributeAutomaticGenerationParamName(), String.valueOf(panel.getAutomaticGeneration()));
                }
                if (!panel.getJsonSerializerClassname().equals(CarmesiFramework.getInstance().getDefaultJsonSerializerClassname())) {
                    parameters.put(CarmesiFramework.getInstance().getJsonSerializerClassnameParamName(), String.valueOf(panel.getJsonSerializerClassname()));
                }
                if (!parameters.isEmpty() && wm.getDeploymentDescriptor() != null) {
                    DDProvider ddProvider = DDProvider.getDefault();
                    WebApp webApp = ddProvider.getDDRoot(wm.getDeploymentDescriptor());
                    for (Map.Entry<String, String> entry : parameters.entrySet()) {
                        InitParam param = (InitParam) webApp.addBean("InitParam");
                        param.setParamName(entry.getKey());
                        param.setParamValue(entry.getValue());
                    }
                    webApp.write(wm.getDeploymentDescriptor());
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            } catch (ClassNotFoundException ex) {
                throw new AssertionError(ex);
            }
        }
        return null;
    }
}
